import { isArray } from "@/utils/is";
import { RouteRecordRaw } from "vue-router";
import { Layout } from "@/routers/constant";

const modules = import.meta.glob('../views/*/*.vue');

/**
 * 使用递归处理路由菜单
 * @param routerList
 */
export function handleRouter(routerList: Menu.MenuOptions[]) {
	let newArr: RouteRecordRaw[] = [];

	routerList.forEach((item: Menu.MenuOptions) => {
		newArr.push(buildRouterItem(item));
	});

	return newArr;
}

export function buildRouterItem(item: Menu.MenuOptions) {
	if (item.component) {
		return {
			path: item.router,
			name: item.component.replace("/", "_"),
			component: modules[`../views/${item.component}.vue`],
			meta: {
				keepAlive: true,
				requiresAuth: true,
				title: item.title,
				key: item.component
			}
		}
	} else {
		if (item.children && item.children.length) {
			let routerItem = {
				path: item.router,
				component: Layout,
				children: [],
				meta: {
					title: item.title,
					requiresAuth: true,
					keepAlive: true
				}
			}

			item.children.forEach((child: Menu.MenuOptions) => {
				routerItem.children?.push(buildRouterItem(child));
			})

			return routerItem;
		}
	}
}

/**
 * @description 获取localStorage
 * @param key Storage名称
 * @returns {String} Storage值
 */
export function localGet(key: string) {
	const value = window.localStorage.getItem(key);
	try {
		return JSON.parse(window.localStorage.getItem(key) as string);
	} catch (error) {
		return value;
	}
}

/**
 * @description 存储localStorage
 * @param key Storage名称
 * @param value Storage值
 */
export function localSet(key: string, value: any) {
	window.localStorage.setItem(key, JSON.stringify(value));
}

/**
 * @description 清除localStorage
 * @param key Storage名称
 */
export function localRemove(key: string) {
	window.localStorage.removeItem(key);
}

/**
 * 清除所有localStorage
 * @returns {String}
 */
export function localClear() {
	window.localStorage.clear();
}

/**
 * @description 对象数组深克隆
 * @param obj 源对象
 * @returns {obj} 克隆后的对象
 */
export function deepCopy<T>(obj: any): T {
	let newObj: any;
	try {
		newObj = obj.push ? [] : {};
	} catch (error) {
		newObj = {};
	}
	for (let attr in obj) {
		if (typeof obj[attr] === "object") {
			newObj[attr] = deepCopy(obj[attr]);
		} else {
			newObj[attr] = obj[attr];
		}
	}
	return newObj;
}

/**
 * @description 判断数据类型
 * @param val 需要判断类型的数据
 * @returns {string} 数据类型
 */
export function isType(val: any) {
	if (val === null) return "null";
	if (typeof val !== "object") return typeof val;
	else return Object.prototype.toString.call(val).slice(8, -1).toLocaleLowerCase();
}

/**
 * @description 生成随机数
 * @param min 最小值
 * @param max 最大值
 * @returns {number}
 */
export function randomNum(min: number, max: number): number {
	let num = Math.floor(Math.random() * (min - max) + max);
	return num;
}

/**
 * @description 获取浏览器默认语言
 * @returns {String} 语言
 */
export function getBrowserLang() {
	let browserLang = navigator.language ? navigator.language : navigator.browserLanguage;
	let defaultBrowserLang = "";
	if (browserLang.toLowerCase() === "cn" || browserLang.toLowerCase() === "zh" || browserLang.toLowerCase() === "zh-cn") {
		defaultBrowserLang = "zh";
	} else {
		defaultBrowserLang = "en";
	}
	return defaultBrowserLang;
}

/**
 * @description 递归查询当前路由所对应的tabPane（暂时没用了）
 * @param menuList 菜单列表
 * @param path 当前地址
 * @returns {Array} 当前路由所对应的tabPane
 */
export function getTabPane<T, U>(menuList: any[], path: U): T {
	let result: any;
	for (let item of menuList || []) {
		if (item.path === path) result = item;
		const res = getTabPane(item.children, path);
		if (res) result = res;
	}
	return result;
}

/**
 * @description 格式化表格单元格默认值
 * @param row 行
 * @param col 列
 * @param callValue 当前单元格值
 * @return {String} 格式化后的值
 * */
export function defaultFormat(row: number, col: number, callValue: any) {
	// 如果当前值为数组,使用 / 拼接（根据需求自定义）
	if (isArray(callValue)) return callValue.length ? callValue.join(" / ") : "--";
	return callValue ?? "--";
}

/**
 * @description 根据枚举列表查询当需要的数据
 * @param callValue 当前单元格值
 * @param enumData 枚举列表
 * @param type 过滤类型（目前只有 tag）
 * @return {String} 格式化后的值
 * */
export function filterEnum(callValue: any, enumData: any[] = [], type?: string): string {
	let filterData = enumData.find(item => item.value === callValue);
	if (type == "tag") return filterData?.tagType ? filterData.tagType : "";
	return filterData ? filterData.label : "--";
}

/**
 * 和PHP一样的时间戳格式化函数
 * @param {string} format 格式
 * @param {int} timestamp 要格式化的时间 默认为当前时间
 * @return {string}   格式化的时间字符串
 */
export const formatDate = (format: string, timestamp: number) => {
	let jsDate = ((timestamp) ? new Date(timestamp * 1000) : new Date())
	let pad = function (n, c) {
		if ((n = n + '').length < c) {
			return new Array(++c - n.length).join('0') + n
		} else {
			return n
		}
	}
	let txt_weekdays = ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday']
	let txt_ord_in = { 1: 'st', 2: 'nd', 3: 'rd', 21: 'st', 22: 'nd', 23: 'rd', 31: 'st' }
	let txt_months = ['', 'January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December']
	let f = {
		d: function () {
			return pad(f.j(), 2)
		},
		D: function () {
			return f.l().substr(0, 3)
		},
		j: function () {
			return jsDate.getDate()
		},
		l: function () {
			return txt_weekdays[f.w()]
		},
		N: function () {
			return f.w() + 1
		},
		S: function () {
			return txt_ord_in[f.j()] ? txt_ord_in[f.j()] : 'th'
		},
		w: function () {
			return jsDate.getDay()
		},
		z: function () {
			return (jsDate - new Date(jsDate.getFullYear() + '/1/1')) / 864e5 >> 0
		},
		W: function () {
			let a = f.z()
			let b = 364 + f.L() - a
			let nd2
			let nd = (new Date(jsDate.getFullYear() + '/1/1').getDay() || 7) - 1
			if (b <= 2 && ((jsDate.getDay() || 7) - 1) <= 2 - b) {
				return 1
			} else {
				if (a <= 2 && nd >= 4 && a >= (6 - nd)) {
					nd2 = new Date(jsDate.getFullYear() - 1 + '/12/31')
					return date('W', Math.round(nd2.getTime() / 1000))
				} else {
					return (1 + (nd <= 3 ? ((a + nd) / 7) : (a - (7 - nd)) / 7) >> 0)
				}
			}
		},
		F: function () {
			return txt_months[f.n()]
		},
		m: function () {
			return pad(f.n(), 2)
		},
		M: function () {
			return f.F().substr(0, 3)
		},
		n: function () {
			return jsDate.getMonth() + 1
		},
		t: function () {
			let n
			if ((n = jsDate.getMonth() + 1) === 2) {
				return 28 + f.L()
			} else {
				// eslint-disable-next-line no-mixed-operators
				if (n & 1 && n < 8 || !(n & 1) && n > 7) {
					return 31
				} else {
					return 30
				}
			}
		},
		L: function () {
			let y = f.Y()
			return (!(y & 3) && (y % 1e2 || !(y % 4e2))) ? 1 : 0
		},
		Y: function () {
			return jsDate.getFullYear()
		},
		y: function () {
			return (jsDate.getFullYear() + '').slice(2)
		},
		a: function () {
			return jsDate.getHours() > 11 ? 'pm' : 'am'
		},
		A: function () {
			return f.a().toUpperCase()
		},
		B: function () {
			let off = (jsDate.getTimezoneOffset() + 60) * 60
			let theSeconds = (jsDate.getHours() * 3600) + (jsDate.getMinutes() * 60) + jsDate.getSeconds() + off
			let beat = Math.floor(theSeconds / 86.4)
			if (beat > 1000) beat -= 1000
			if (beat < 0) beat += 1000
			if ((String(beat)).length === 1) beat = '00' + beat
			if ((String(beat)).length === 2) beat = '0' + beat
			return beat
		},
		g: function () {
			return jsDate.getHours() % 12 || 12
		},
		G: function () {
			return jsDate.getHours()
		},
		h: function () {
			return pad(f.g(), 2)
		},
		H: function () {
			return pad(jsDate.getHours(), 2)
		},
		i: function () {
			return pad(jsDate.getMinutes(), 2)
		},
		s: function () {
			return pad(jsDate.getSeconds(), 2)
		},
		O: function () {
			let t = pad(Math.abs(jsDate.getTimezoneOffset() / 60 * 100), 4)
			if (jsDate.getTimezoneOffset() > 0) t = '-' + t; else t = '+' + t
			return t
		},
		P: function () {
			let O = f.O()
			return (O.substr(0, 3) + ':' + O.substr(3, 2))
		},
		c: function () {
			return f.Y() + '-' + f.m() + '-' + f.d() + 'T' + f.h() + ':' + f.i() + ':' + f.s() + f.P()
		},
		U: function () {
			return Math.round(jsDate.getTime() / 1000)
		}
	}

	let exp = /[\\]?([a-zA-Z])/g
	return format.replace(exp, function (t, s) {
		let ret = ''
		if (t !== s) {
			ret = s
		} else if (f[s]) {
			ret = f[s]()
		} else {
			ret = s
		}
		return ret
	})
}
